// CommandLine Presenter

/// <reference path="../typings/jquery/jquery.d.ts" />
/// <reference path="../typings/jquery/jqueryui.d.ts" />

// import UI interfaces
import I = require("./Interfaces");

// import instructions
import Instr = require("../MiddleLayer/Execution/Instructions");

// import the dictionary module
import Dic = require("../MiddleLayer/Execution/Dictionary");

// import messagebox
import MsgBox = require("./MessageBox");

// import execution engine
import Exec = require("../MiddleLayer/Execution/ExecutionEngine");

// import Robot Karel
import Karel = require("../MiddleLayer/Execution/RobotKarel");


export class CommandLine implements I.ICommandLine {

    // Karel's city renderer
    private mCityRenderer: I.ICityRenderer;

    // Karel's dictionary
    private mDictionary: Dic.Dictionary;
    private mKarel: Karel.RobotKarel;

    // reference to the execution engine
    private mEngine: Exec.ExecutionEngine;
    
    // constructor
    public constructor(cityRenderer: I.ICityRenderer) {
        // init vars
        this.mCityRenderer = cityRenderer;

        // set references
        this.mDictionary = Dic.Dictionary.Instance;
        this.mEngine = Exec.ExecutionEngine.Instance;
        this.mKarel = Karel.RobotKarel.Instance;

        // build the control
        this.BuildControl();
    }

    // builds the control
    private BuildControl(): void {
        var that = this;

        // register the redraw handler
        this.mDictionary.SetRedrawHandler(function () {
            that.mCityRenderer.Render();
        });

        // register handler for Karel's exception
        this.mDictionary.SetKarelExceptionHandler(function (type) {
            // switch the exception type
            that.Update();

            // save city          
            that.mKarel.Save();

            switch (type) {
                case Instr.eKarelException.CannotMove:
                    MsgBox.MessageBox.Instance.ShowModal("KarelCannotMove", "KarelErrorTitle");
                    break;
                case Instr.eKarelException.NoMark:
                    MsgBox.MessageBox.Instance.ShowModal("KarelNoMark", "KarelErrorTitle");
                    break;
                case Instr.eKarelException.TooManyMarks:
                    MsgBox.MessageBox.Instance.ShowModal("KarelTooManyMarks", "KarelErrorTitle");
                    break;
                case Instr.eKarelException.Tired:
                    MsgBox.MessageBox.Instance.ShowModal("KarelTired", "KarelErrorTitle");
                    break;
            }
        });

        // handle the end of command execution
        this.mDictionary.SetExecutionCompleted(function () {
            // save city          
            that.mKarel.Save();
            
            // update UI
            that.Update();
        });

        // create autocomplete 
        $("#idCommandLineInput").autocomplete({
            source: function (request, response) {
                var commands = that.mDictionary.GetListOfCommands();
                var output = new Array<string>();
                var prefix = request.term.toLocaleLowerCase();

                for (var i = 0; i < commands.length; i++) {
                    var cmd = commands[i].toLocaleLowerCase();
                    if (cmd.indexOf(prefix) >= 0) {
                        output.push(cmd);
                    }
                }

                response(output);
            },        
        });

        // hook on "Enter" key
        $("#idCommandLineInput").bind("keyup", function (event) {
            if (event.keyCode == 13) {
                var commandName = $("#idCommandLineInput").val();
                $("#idCommandLineInput").val("");
                that.RunCommand(commandName);
            }
        });
    }

    // updates the command line
    public Update() {
        // enable / disable the command line
        var enabled = this.mEngine.IsRunning == false;
        if (enabled) {
            $("#idCommandLineInput").removeAttr("disabled");
        }
        else {
            $("#idCommandLineInput").attr("disabled", "disabled");
        }
    }

    // runs the command
    public RunCommand(commandName: string): void {
        this.mDictionary.RunCommand(commandName);
        this.Update();
        this.mCityRenderer.Render();
    }

    // sets focus to the command line
    public FocusCommandLine(): void {
        if (this.mEngine.IsRunning == false) {
            $("#idCommandLineInput").focus();
        }
    }
}
